require('winston-daily-rotate-file');
require('winston');
const expressWinston = require('express-winston');
const {
    LOG_LEVEL,
    LOG_FILE_SIZE,
    LOG_FILE_COUNT,
    LOG_FREQUENCY,
    LOG_DATE_FORMAT,
    LOG_FILE_NAME,
    LOG_FILE_DIR
} = require("./settings")
const {getStackInfo} = require("./utils")
const {createLogger, transports, format} = require("winston");


const myFormat = format.printf(({level, label, message, fileName, lineNo, timestamp}) => {
    let levelUp = level.toUpperCase()
    // let msgStr = JSON.stringify(message)
    return `${timestamp} [${label}] [${fileName}] [${lineNo} Line] [${levelUp}]: ${message}`;
});
const consoleTransport = new transports.Console(
    {
        level: LOG_LEVEL,
        handleExceptions: true,
        format: format.combine(
            format.label({label: "ExpressApp"}),
            format.timestamp({format: LOG_DATE_FORMAT}),
            // format.
            // format.colorize(),
            // format.simple()
            myFormat
        )
    }
)
const fileTransport = new (transports.DailyRotateFile)({
    level: LOG_LEVEL,
    dirname: LOG_FILE_DIR,
    filename: LOG_FILE_NAME,
    datePattern: 'YYYY-MM-DD',
    format: format.combine(
        format.label({label: "ExpressApp"}),
        format.timestamp({format: LOG_DATE_FORMAT}),
        // format.simple()
        myFormat
    ),
    handleExceptions: true,
    handleRejections: true,
    frequency: LOG_FREQUENCY,
    zippedArchive: true,
    maxSize: LOG_FILE_SIZE,
    maxFiles: LOG_FILE_COUNT
})
const LOGGER = createLogger({
    transports: [
        consoleTransport,
        fileTransport
    ],
    exceptionHandlers: [
        consoleTransport,
        fileTransport
    ],
    rejectionHandlers: [
        consoleTransport,
        fileTransport
    ],
    exitOnError: true

});

expressWinston.logger = (options = {}) => {
    const winstonInstance = options.winstonInstance || createLogger({
        transports: [consoleTransport, fileTransport]
    });
    return (req, res, next) => {
        const startTime = new Date();
        const stackInfo = getStackInfo()
        let reqBody=""
        let responseBody;
        req.on('data', (chunk) =>{
            reqBody += chunk
        })


        req.on('end', () => {

            const logEntry = {
                message: `${req.protocol.toUpperCase()} [${req.hostname} => SERVER] Request ${req.method} ${req.originalUrl} QueryParam: ${JSON.stringify(req.query)} Body: ${reqBody.replace("undefined","")}`,
                body: req.body, // 添加请求体
                query: req.query,
                headers: req.headers,
                method: req.method,
                originalUrl: req.originalUrl,
                protocol: req.protocol,
                ip: req.ip,
                user: req.user,
                serverName: req.hostname,
                serverTime: new Date().toJSON(),
            };
            logEntry.fileName = stackInfo.fileName
            logEntry.lineNo = stackInfo.line
            winstonInstance.info(logEntry);
        });
        res.on('data', (chunk) => {
            responseBody += chunk;
        });
        res.on('finish', () => {

            let responseTime = (new Date() - startTime);
            const logResEntry = {
                message: `${req.protocol.toUpperCase()} [SERVER => ${req.hostname}] Response ${responseTime}ms ${res.statusCode} ${req.originalUrl}`,

            };
            logResEntry.fileName = stackInfo.fileName
            logResEntry.lineNo = stackInfo.line

            winstonInstance.debug(logResEntry);
        });

        next && next();
    };
};

const EXPRESS_LOGGER = expressWinston.logger({
    expressFormat: false,
    colorize: false,
    meta: true,

})
LOGGER.info = (message, meta) => {
    const stackInfo = getStackInfo()
    // 调用原始的 info() 方法进行日志输出
    LOGGER.log("info", message, {fileName: stackInfo["fileName"], lineNo: stackInfo["line"]});
};

LOGGER.error = (message, meta) => {
    const stackInfo = getStackInfo()
    // 调用原始的 info() 方法进行日志输出
    LOGGER.log("error", message, {fileName: stackInfo["fileName"], lineNo: stackInfo["line"]});
};

LOGGER.debug = (message, meta) => {
    const stackInfo = getStackInfo()
    // 调用原始的 info() 方法进行日志输出
    LOGGER.log("debug", message, {fileName: stackInfo["fileName"], lineNo: stackInfo["line"]});
};



module.exports = {
    LOGGER, EXPRESS_LOGGER
}
